﻿//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Globalization;
//using System.Reflection;
//using ArgusPCLib.Mathematics.Reflection;

//namespace ArgusPCLib.Mathematics
//{
//	public class Expression
//	{
//		public IOperand[] OperandStack { get; private set; }
//		public IOperator[] OperatorStack { get; private set; }

//		public Expression(IOperand[] operandStack, IOperator[] operatorStack)
//		{
//			this.OperandStack = operandStack;
//			this.OperatorStack = operatorStack;
//		}

//		public static Expression Parse(IEnumerable<IOperator> allowedOperators, string expression, IFormatProvider formatProvider)
//		{
//			ExpressionFormatInfo efi = ExpressionFormatInfo.GetInstance(formatProvider);
//			Dictionary<string, List<IOperator>> groupedOperators = allowedOperators.Group(
//				new Func<IOperator, string>((op) => { return op.GetSymbol(efi.CultureInfo); }));

//			Dictionary<string, List<IOperator>> parsedOperators = new Dictionary<string, List<IOperator>>();
//			List<string> expressionParts = new List<string>();

//			int start = 0;
//			for (int i = 0; i < expression.Length; i++)
//			{
//				foreach(KeyValuePair<string,List<IOperator>> item in groupedOperators)
//				{
//					if (string.Compare(expression, i, item.Key, 0, item.Key.Length) != 0)
//						continue;

//					if (i > start)
//						expressionParts.Add(expression.Substring(start, i - start));
//					parsedOperators.Add(item.Key, item.Value);
//					start = i + item.Key.Length;
//					i = start - 1;
//					break;
//				}
//			}
//			if (start < expression.Length)
//				expressionParts.Add(expression.Substring(start));

//			List<IOperator> operatorStack = new List<IOperator>(parsedOperators.Count);
//		}

//		public static Expression Parse(Type operandType, string expression, IFormatProvider formatProvider)
//		{
//			ExpressionFormatInfo efi = ExpressionFormatInfo.GetInstance(formatProvider);
//			Type[] operandTypes;
//			IOperator[] operators;
//			Expression.GetOperandsAndOperators(operandType, out operandTypes, out operators);
//			string[] opSymbols = new string[operators.Length];
//			for (int i = 0; i < operators.Length; i++)
//				opSymbols[i] = operators[i].GetSymbol(efi.CultureInfo);

//			List<IOperator> operatorStack = new List<IOperator>();
//			List<string> expressionParts = new List<string>();

//			int start = 0;
//			for (int i = 0; i < expression.Length; i++)
//			{
//				for (int j = 0; j < operators.Length; j++)
//				{
//					if (string.Compare(expression, i, opSymbols[j], 0, opSymbols[j].Length) != 0)
//						continue;

//					if (i > start)
//						expressionParts.Add(expression.Substring(start, i - start));
//					operatorStack.Add(operators[j]);
//					start = i + opSymbols[j].Length;
//					i = start - 1;
//					break;
//				}
//			}
//			if (start < expression.Length)
//				expressionParts.Add(expression.Substring(start));

//			return null;
//		}

//		static void GetOperandsAndOperators(Type operandType, out Type[] operandTypes, out IOperator[] operators)
//		{
//			List<IOperator> lOperators = new List<IOperator>();
//			List<Type> operatorTypes = new List<Type>();
//			List<Type> lOperandTypes = new List<Type>();
//			lOperandTypes.Add(operandType);
//			for (int i = 0; i < lOperandTypes.Count; i++)
//			{
//				Type[] opTypes = OperandReflector.GetOperators(lOperandTypes[i]);
//				foreach (Type opType in opTypes)
//				{
//					if (operatorTypes.Contains(opType))
//						continue;
//					IOperator op = OperatorReflector.GetInstance(opType);
//					lOperators.Add(op);
//					Func<IOperand[], IOperand>[] funcs = op.GetApplyOperatorOverloads();
//					foreach (Func<IOperand[], IOperand> func in funcs)
//					{
//						ParameterInfo[] pis = func.Method.GetParameters();
//						foreach (ParameterInfo pi in pis)
//						{
//							if (!lOperandTypes.Contains(pi.ParameterType))
//								lOperandTypes.Add(pi.ParameterType);
//						}
//					}
//				}
//			}
//			operandTypes = lOperandTypes.ToArray();
//			operators = lOperators.ToArray();
//		}

//		//public static IOperand Calculate(Type operandType, string expression)
//		//{
//		//	List<IOperand> operandStack;
//		//	List<IOperator> operatorStack;
//		//	if (Expression.ParseExpression(operandType, expression, out operandStack, out operatorStack) == false)
//		//		throw new ArgumentException("Invalid Expression.", "expression");

//		//	while (operatorStack.Count > 0)
//		//	{
//		//		IOperator op = operatorStack[0];
//		//		int operatorIndex = 0;
//		//		for (int i = 1; i < operatorStack.Count; i++)
//		//		{
//		//			if (operatorStack[i].Precedence > op.Precedence)
//		//			{
//		//				op = operatorStack[i];
//		//				operatorIndex = i;
//		//			}
//		//			else
//		//				break;
//		//		}
//		//		operatorStack.RemoveAt(operatorIndex);
//		//		int operandIndex = 0;
//		//		for (int i = 0; i < operatorIndex; i++)
//		//		{
//		//			operandIndex += operatorStack[i].RequiredOperands - 1;
//		//		}

//		//		IOperand[] operands = new IOperand[op.RequiredOperands];
//		//		for (int i = 0; i < op.RequiredOperands; i++)
//		//			operands[i] = operandStack[operandIndex + i];
//		//		operandStack.RemoveRange(operandIndex, op.RequiredOperands);

//		//		IOperand result = op.ApplyOperator(operands);
//		//		operandStack.Insert(operandIndex, result);
//		//	}

//		//	if (operandStack.Count != 1)
//		//		throw new ArgumentException("Invalid Expression: Number of actual operands and number operands required by operators do not match.", "expression");
//		//	return operandStack[0];
//		//}

//		//public static bool TryParse(Type[] operandTypes, string expression, out List<IOperand> operandStack, out List<IOperator> operatorStack)
//		//{
//		//	IOperator[] operators;
//		//	{
//		//		Type[] operatorTypes = OperandReflector.GetOperators(operandType);
//		//		operators = new IOperator[operatorTypes.Length];
//		//		for (int i = 0; i < operatorTypes.Length; i++)
//		//			operators[i] = OperatorReflector.GetInstance(operatorTypes[i]);
//		//	}

//		//	operandStack = new List<IOperand>();
//		//	operatorStack = new List<IOperator>();

//		//	OperandPartialParseHandler partialParseHandler = OperandReflector.GetPartialParseHandler(operandType);

//		//	for (int i = 0; i < expression.Length; i++)
//		//	{
//		//		if (char.IsWhiteSpace(expression[i]))
//		//			continue;

//		//		IOperand operand;
//		//		int count = partialParseHandler(expression, i, null, null, out operand);
//		//		if (count > 0)
//		//		{
//		//			operandStack.Add(operand);
//		//			i += count;
//		//			continue;
//		//		}
//		//		bool opFound = false;
//		//		foreach (IOperator op in operators)
//		//		{
//		//			if (string.Compare(expression, i, op.Symbol, 0, op.Symbol.Length) == 0)
//		//			{
//		//				operatorStack.Add(op);
//		//				i += op.Symbol.Length;
//		//				opFound = true;
//		//				break;
//		//			}
//		//		}
//		//		if (opFound)
//		//			continue;

//		//		if (expression[i] == '(')
//		//		{
//		//			int end;
//		//			int brackets = 1;
//		//			for (end = i + 1; end < expression.Length; end++)
//		//			{
//		//				if (expression[end] == ')')
//		//					brackets--;
//		//				else if (expression[end] == '(')
//		//					brackets++;

//		//				if (brackets == 0)
//		//					break;
//		//			}

//		//			if (brackets != 0)
//		//				return false;

//		//			IOperand bOperand = Expression.Calculate(operandType, expression.Substring(i + 1, end - i));
//		//			operandStack.Add(bOperand);
//		//			i = end;
//		//			continue;
//		//		}

//		//		return false;
//		//	}
//		//	return true;
//		//}
//	}
//}
